home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs49.d81 / hack2-3.sfx / hack.3
Text File  |  1990-02-12  |  30KB  |  1,002 lines

  1. .%0200!  ;*** FETCH( [ZP1]=╞AR╙OURCE, (ZW1)=╥AM0─EST, .┴┘=╠ENGTH )
  2. .%0201!
  3.  
  4. ╙OME WORKING STORAGE LOCATIONS ARE NECESSARY FOR THIS ROUTINE, SINCE IT IS
  5. DESIGNED TO COPY DATA A PAGE AT A TIME.  ╘HE SOURCE (ZP1+1) AND DESTINATION
  6. (ZW1+1) PAGE ADDRESSES ARE SAVED AND LATER RESTORED BECAUSE THIS ROUTINE
  7. ALTERS THEM WHILE COPYING.  ╔F THE FAR ADDRESS IS IN EXPANSION MEMORY, THIS
  8. ROUTINE DISPATCHES TO THE ╥┼╒ FETCH/STASH CODE.
  9.  
  10. .%0202!  FETCH╠ENGTH = SYS╫ORK
  11. .%0203!  FETCH╙AVE╙OURCE = SYS╫ORK+2
  12. .%0204!  FETCH╙AVE─EST = SYS╫ORK+3
  13. .%0205!
  14. .%0206!  INTERN╥AM0╞ETCH = *
  15. .%0207!     LDX ZP1+2
  16. .%0208!     BPL +
  17. .%0209!     LDX #$91
  18. .%0210!     JMP DO╥EU
  19.  
  20. ╔F THE TRANSFER IS LESS THAN ONE PAGE LONG, IT CAN BE DONE BY CALLING THE
  21. FETCH╨AGE CODE DIRECTLY.  ╧THERWISE, THE LONG FETCH CODE HAS TO BE CALLED.
  22.  
  23. .%0211!  +  CPY #0
  24. .%0212!     BNE FETCH╠ONG
  25. .%0213!     TAY
  26. .%0214!     BNE FETCH╨AGE
  27. .%0215!     RTS
  28. .%0216!
  29.  
  30. ╔F THE (INTERNAL) PAGE TO BE FETCHED IS ON ╥┴═1, THE COMMON CODE ROUTINE IS
  31. CALLED; OTHERWISE, THE COPY IS DONE HERE BY SWITCHING ╥┴═0 INTO CONTEXT.  ╫E
  32. CAN COPY BETWEEN ╥┴═0 LOCATIONS WITHOUT SWITCHING CONTEXTS FOR EVERY BYTE.
  33.  
  34. .%0217!     FETCH╨AGE = *
  35. .%0218!     CPX #BK╥AM0
  36. .%0219!     BEQ +
  37. .%0220!     JMP COM├OPY╥AM1╘O╥AM0-COM├ODE╙TART+COM├ODE┬UFFER
  38. .%0221!  +  STX BK╙ELECT
  39. .%0222!     DEY
  40. .%0223!     BEQ +
  41. .%0224!  -  LDA (ZP1),Y
  42. .%0225!     STA (ZW1),Y
  43. .%0226!     DEY
  44. .%0227!     BNE -
  45. .%0228!  +  LDA (ZP1),Y
  46. .%0229!     STA (ZW1),Y
  47. .%0230!     LDA #BK╙YS
  48. .%0231!     STA BK╙ELECT
  49. .%0232!     RTS
  50. .%0233!
  51.  
  52. ╘HIS IS CALLED FOR LONG (>=256 BYTE) (INTERNAL) FETCHES.  ╔T CALLS THE
  53. FETCH╨AGE CODE REPEATEDLY, AFTER INCREMENTING THE SOURCE AND DESTINATION PAGE
  54. NUMBERS.  ╘HE TRANSFER LENGTH IS DECREMENTED UNTIL IT IS LESS THAN 256 BYTES.
  55.  
  56. .%0234!     FETCH╠ONG = *
  57. .%0235!     STA FETCH╠ENGTH
  58. .%0236!     STY FETCH╠ENGTH+1
  59. .%0237!     LDA ZP1+1
  60. .%0238!     STA FETCH╙AVE╙OURCE
  61. .%0239!     LDA ZW1+1
  62. .%0240!     STA FETCH╙AVE─EST
  63. .%0241!     LDA FETCH╠ENGTH+1
  64. .%0242!     BEQ FETCH╠ONG┼XIT
  65. .%0243!  -  LDX ZP1+2
  66. .%0244!     LDY #0
  67. .%0245!     JSR FETCH╨AGE
  68. .%0246!     INC ZP1+1
  69. .%0247!     INC ZW1+1
  70. .%0248!     DEC FETCH╠ENGTH+1
  71. .%0249!     BNE -
  72. .%0250!
  73. .%0251!     FETCH╠ONG┼XIT = *
  74.  
  75. ╘HIS FETCHES THE LAST CHUNK OF LESS THAN 256 BYTES AND THEN RESTORES THE ZP1
  76. AND ZW1 PARAMETERS TO WHAT THEY WERE BEFORE THIS ROUTINE WAS CALLED.
  77.  
  78. .%0252!     LDY FETCH╠ENGTH
  79. .%0253!     BEQ +
  80. .%0254!     LDX ZP1+2
  81. .%0255!     JSR FETCH╨AGE
  82. .%0256!  +  LDA FETCH╙AVE╙OURCE
  83. .%0257!     STA ZP1+1
  84. .%0258!     LDA FETCH╙AVE─EST
  85. .%0259!     STA ZW1+1
  86. .%0260!     RTS
  87. .%0261!
  88. .%0262!  ;*** STASH( (ZW1)=╥AM0╙OURCE, [ZP1]=╞AR─EST, .┴┘=LENGTH )
  89. .%0263!
  90.  
  91. ╙TASH HAS EXACTLY THE SAME STRUCTURE AS FETCH.
  92.  
  93. .%0264!  STASH╠ENGTH = SYS╫ORK
  94. .%0265!  STASH╙AVE╙OURCE = SYS╫ORK+2
  95. .%0266!  STASH╙AVE─EST = SYS╫ORK+3
  96. .%0267!
  97. .%0268!  INTERN╥AM0╙TASH = *
  98. .%0269!     LDX ZP1+2
  99. .%0270!     BPL +
  100. .%0271!     LDX #$90
  101. .%0272!     JMP DO╥EU
  102. .%0273!  +  CPY #0
  103. .%0274!     BNE STASH╠ONG
  104. .%0275!     TAY
  105. .%0276!     BNE STASH╨AGE
  106. .%0277!     RTS
  107. .%0278!
  108. .%0279!     STASH╨AGE = *
  109. .%0280!     CPX #BK╥AM0
  110. .%0281!     BEQ +
  111. .%0282!     JMP COM├OPY╥AM0╘O╥AM1-COM├ODE╙TART+COM├ODE┬UFFER
  112. .%0283!  +  STX BK╙ELECT
  113. .%0284!     DEY
  114. .%0285!     BEQ +
  115. .%0286!  -  LDA (ZW1),Y
  116. .%0287!     STA (ZP1),Y
  117. .%0288!     DEY
  118. .%0289!     BNE -
  119. .%0290!  +  LDA (ZW1),Y
  120. .%0291!     STA (ZP1),Y
  121. .%0292!     LDA #BK╙YS
  122. .%0293!     STA BK╙ELECT
  123. .%0294!     RTS
  124. .%0295!
  125. .%0296!     STASH╠ONG = *
  126. .%0297!     STA STASH╠ENGTH
  127. .%0298!     STY STASH╠ENGTH+1
  128. .%0299!     LDA ZW1+1
  129. .%0300!     STA STASH╙AVE╙OURCE
  130. .%0301!     LDA ZP1+1
  131. .%0302!     STA STASH╙AVE─EST
  132. .%0303!     LDA STASH╠ENGTH+1
  133. .%0304!     BEQ STASH╠ONG┼XIT
  134. .%0305!  -  LDX ZP1+2
  135. .%0306!     LDY #0
  136. .%0307!     JSR STASH╨AGE
  137. .%0308!     INC ZP1+1
  138. .%0309!     INC ZW1+1
  139. .%0310!     DEC STASH╠ENGTH+1
  140. .%0311!     BNE -
  141. .%0312!
  142. .%0313!     STASH╠ONG┼XIT = *
  143. .%0314!     LDY STASH╠ENGTH
  144. .%0315!     BEQ +
  145. .%0316!     LDX ZP1+2
  146. .%0317!     JSR STASH╨AGE
  147. .%0318!  +  LDA STASH╙AVE╙OURCE
  148. .%0319!     STA ZW1+1
  149. .%0320!     LDA STASH╙AVE─EST
  150. .%0321!     STA ZP1+1
  151. .%0322!     RTS
  152. .%0323!
  153. .%0324!  ;*** RAM0 LOAD/STORE(.╪) EXPN MEMORY [ZP1] <- -> (ZW1) FOR .┴┘ BYTES
  154. .%0325!
  155.  
  156. ╘HIS IS THE CODE THAT DOES THE FETCHING AND STASHING FROM/TO EXPANSION
  157. MEMORY.  ╘HE ONLY DIFFERENCE BETWEEN A FETCH AND A STASH IS THE ╥┼╒ ├ONTROLLER
  158. COMMAND CODE, SO THAT IS AN INPUT PARAMETER.  ╘HE ╥┼╒ ├ONTROLLER REGISTERS ARE
  159. SET UP, THE CLOCK IS SLOWED, THE TRANSFER HAPPENS, AND THEN THE CLOCK SPEED IS
  160. RESTORED.  ╘HE BULK TRANSFER IS DONE ENTIRELY BY THE ╥┼╒ ├ONTROLLER.
  161. ╔NTERESTINGLY, IT WOULD HAVE BEEN FASTER TO TRANSFER THE INTERNAL MEMORY TO
  162. EXPANSION MEMORY AND THEN FETCH IT BACK AGAIN IN ORDER TO ACHIEVE AN INTERNAL
  163. MEMORY TRANSFER (IF YOU HAVE AN ╥┼╒), BUT ╔ DIDN'T BOTHER WITH THAT.
  164.  
  165. .%0326!  DO╥EU = *
  166. .%0327!     STA REU+7
  167. .%0328!     STY REU+8
  168. .%0329!     LDA ZW1
  169. .%0330!     LDY ZW1+1
  170. .%0331!     STA REU+2
  171. .%0332!     STY REU+3
  172. .%0333!     LDA ZP1
  173. .%0334!     LDY ZP1+1
  174. .%0335!     STA REU+4
  175. .%0336!     STY REU+5
  176. .%0337!     LDA ZP1+2
  177. .%0338!     STA REU+6
  178. .%0339!     LDY VIC+$30
  179. .%0340!     LDA #0
  180. .%0341!     STA VIC+$30
  181. .%0342!     STX REU+1
  182. .%0343!     STY VIC+$30
  183. .%0344!     RTS
  184. .%0345!
  185. .%0346!  ;*** SNIFF╥┼╒ - DETERMINE NUMBER OF BANKS OF EXPANSION MEMORY
  186. .%0347!
  187.  
  188. ╘HE WORK LOCATIONS ARE USED TO STORE A STRING TO THE FIRST FOUR ADDRESSES OF
  189. EACH EXPANSION MEMORY BANK AND THEN FETCH THEM BACK AGAIN IN ORDER TO
  190. DETERMINE WHETHER THE BANK EXISTS OR NOT.  ┼XPANSION BANK #0 IS ALSO CHECKED
  191. AFTER EACH BANK TO SEE IF A BANK NUMBER WRAP-AROUND OCCURED.  ╘HE
  192. "REU╙IZE╠IMIT" WILL FORCE THIS ROUTINE TO STOP SEARCHING AFTER THAT NUMBER OF
  193. BANKS HAVE BEEN SNIFFED.  ╘HE MAXIMUM VALUE IS 127, SINCE ONLY BANK NUMBERS
  194. $80 TO $╞┼ ARE AVAILABLE.  ┬Y CHANGING THIS VALUE, YOU CAN STOP THIS PACKAGE
  195. FROM USING EXPANSION MEMORY RESERVED BY ANOTHER PROGRAM.  ╬OTE THAT THIS
  196. PROGRAM USES EXPANSION BANKS 0 UP TO BUT NOT INCLUDING "REU╙IZE╠IMIT".
  197.  
  198. .%0348!  SNIFF╫ORK1 = SYS╫ORK
  199. .%0349!  SNIFF╫ORK2 = SYS╫ORK+4
  200. .%0350!  REU╙IZE╠IMIT .BYTE 127
  201. .%0351!
  202. .%0352!  SNIFF╥┼╒ = *
  203.  
  204. ╚ERE ╔ SAVE THE DATA IN THE MEMORY "BENEATH" THE ╥┼╒ ├ONTROLLER REGISTERS.  ╔F
  205. THERE ISN'T A ╥┼╒ INSTALLED, THIS MEMORY WOULD OTHERWISE BE CORRUPTED BY ╔/╧
  206. ADDRESSES BLEEDING THROUGH TO THE UNDERLYING ╥┴═.
  207.  
  208. .%0353!     LDA #BK╥AM0
  209. .%0354!     STA BK╙ELECT
  210. .%0355!     LDX #$A
  211. .%0356!  -  LDA REU,X
  212. .%0357!     STA WORK┬UFFER,X
  213. .%0358!     DEX
  214. .%0359!     BPL -
  215. .%0360!     LDA #BK╙YS
  216. .%0361!     STA BK╙ELECT
  217.  
  218. ╚ERE ╔ INITIALIZE THE CONFIGURATION ╥┼╒ ├ONTROLLER REGSTERS.  ╘HEY ARE SET
  219. ONLY ONCE BY THIS PACKEAGE.
  220.  
  221. .%0362!     LDA #$00
  222. .%0363!     STA REU+$9
  223. .%0364!     STA REU+$A
  224. .%0365!     LDA REU+$0
  225.  
  226. ╘HE THREE-BYTE IDENTIFIER STRING IS COPIED INTO THE SOURCE TAG.  ╘HE FOURTH
  227. BYTE WILL BE FILLED IN BY THE BANK NUMBER.
  228.  
  229. .%0366!     LDX #2
  230. .%0367!  -  LDA EXP╥AM╔D,X
  231. .%0368!     STA SNIFF╫ORK1,X
  232. .%0369!     DEX
  233. .%0370!     BPL -
  234.  
  235. ╔NITIALIZATION CONTINUES.
  236.  
  237. .%0371!     LDA #0
  238. .%0372!     STA N┼XP┬ANKS
  239. .%0373!     LDA #$00
  240. .%0374!     LDX #BK┼XP0
  241. .%0375!     STA ZP1
  242. .%0376!     STA ZP1+1
  243. .%0377!     STX ZP1+2
  244. .%0378!
  245.  
  246. ╘HIS IS THE MAIN LOOP.  ╔T TESTS THE CURRENT EXPANSION BANK AND THEN GOES ON
  247. TO THE NEXT ONE IF OK.  ╧THERWISE, IT STOPS AT THE NUMBER OF OKAY BANKS.
  248.  
  249. .%0379!  -  JSR TEST┼XP┬ANK
  250. .%0380!     BCS +
  251. .%0381!     INC N┼XP┬ANKS
  252. .%0382!     INC ZP1+2
  253. .%0383!     BNE -
  254. .%0384!  +  LDA N┼XP┬ANKS
  255. .%0385!     BNE +
  256.  
  257. ╥ESTORE THE UNDERLYING ╥┴═ CONTENTS AND EXIT.
  258.  
  259. .%0386!     LDA #BK╥AM0
  260. .%0387!     STA BK╙ELECT
  261. .%0388!     LDX #$A
  262. .%0389!  -  LDA WORK┬UFFER,X
  263. .%0390!     STA REU,X
  264. .%0391!     DEX
  265. .%0392!     BPL -
  266. .%0393!     LDA #BK╙YS
  267. .%0394!     STA BK╙ELECT
  268. .%0395!  +  RTS
  269. .%0396!
  270. .%0397!  ;*** TEST EXPANSION BANK( [ZP1]=┬ANK╨TR ) : .├├=OK
  271. .%0398!
  272.  
  273. ╞IRST CHECKS THAT THE MAXIMUM NUMBER OF ALLOWED EXPANSION BANKS HAS NOT BEEN
  274. EXCEEDED.  ╙TORES THE TEST STRING THROUGH THE BANK POINTER AND THEN TESTS TO
  275. SEE THAT THE STRING HAS BEEN STORED CORRECTLY AND THAT THE STRING ON EXPANSION
  276. BANK 0 IS STILL OK (IT WOULDN'T BE OK IF A WRAP-AROUND OCCURED).
  277.  
  278. .%0399!  TEST┼XP┬ANK = *
  279. .%0400!     LDA N┼XP┬ANKS
  280. .%0401!     CMP REU╙IZE╠IMIT
  281. .%0402!     BCC +
  282. .%0403!     RTS
  283. .%0404!  +  LDA ZP1+2
  284. .%0405!     STA SNIFF╫ORK1+3
  285. .%0406!     LDX #SNIFF╫ORK1
  286. .%0407!     LDY #4
  287. .%0408!     JSR ZPSTORE
  288. .%0409!     JSR TEST┼XP┬ANK╔NTERNAL  ;TEST CURRENT BANK
  289. .%0410!     BCS +
  290. .%0411!     LDA ZP1+2
  291. .%0412!     PHA
  292. .%0413!     LDA #BK┼XP0
  293. .%0414!     STA ZP1+2
  294. .%0415!     STA SNIFF╫ORK1+3
  295. .%0416!     JSR TEST┼XP┬ANK╔NTERNAL  ;TEST EXPANSION BANK 0
  296. .%0417!     PLA
  297. .%0418!     STA ZP1+2
  298. .%0419!  +  RTS
  299. .%0420!
  300.  
  301. ╘HIS ROUTINE READS THE BYTES AT ADDRESS [ZP1] AND MAKES SURE THEY ARE THE SAME
  302. AS THE PREVIOUS ROUTINE PUT THERE.  ╧N RETURN, THE CARRY FLAG IS SET IF THE
  303. STRING FOUND IS NOT THE SAME AS WHAT WAS PREVIOUSLY PUT OUT.
  304.  
  305. .%0421!  TEST┼XP┬ANK╔NTERNAL = *
  306. .%0422!     LDA #$00
  307. .%0423!     STA SNIFF╫ORK2
  308. .%0424!     STA SNIFF╫ORK2+3
  309. .%0425!     LDX #SNIFF╫ORK2
  310. .%0426!     LDY #4
  311. .%0427!     JSR ZPLOAD
  312. .%0428!     LDX #3
  313. .%0429!  -  LDA SNIFF╫ORK2,X
  314. .%0430!     CMP SNIFF╫ORK1,X
  315. .%0431!     BNE +
  316. .%0432!     DEX
  317. .%0433!     BPL -
  318. .%0434!     CLC
  319. .%0435!     RTS
  320. .%0436!  +  SEC
  321. .%0437!     RTS
  322. .%0438!
  323.  
  324. ╘HIS IS THE THREE-BYTE STRING PUT INTO THE EXPANSION BANKS.  ╘HE VALUE MEANS
  325. "╥┴═ IDENTIFIER".
  326.  
  327. .%0439!  EXP╥AM╔D   .BYTE "R"
  328. .%0440!             .BYTE "╔"
  329. .%0441!             .BYTE "D"
  330. .%0442!
  331. .%0443!  ;--------------------------------------------------------------------
  332. .%0444!  ;*** INITIALIZE DYNAMICALLY ALLOCATED MEMORY() : N┼XP┬ANKS
  333. .%0445!
  334.  
  335. ╘HIS ROUTINE CALLS "FREE" TO INITIALIZE THE FREE MEMORY ON EACH EXISTING
  336. BANK.  ╥┴═0 IS SET TO BE FREE FROM $4000 TO THE TOP OF ┬┴╙╔├ MEMORY, SO YOU'LL
  337. HAVE TO CHANGE THE "RAM0╞REE╙TART╨AGE" PARAMETER IF YOU WANT TO HAVE A PROGRAM
  338. THAT OCCUPIES MEMORY HIGHER THAN THIS ADDRESS.  ╥┴═1 IS DECLARED TO BE FREE
  339. FROM $0400 TO $╞┼╞╞
  340.  
  341. .%0446!  RAM0╞REE╙TART╨AGE .BYTE $40
  342. .%0447!  RAM1╞REE╙TART╨AGE .BYTE $04
  343. .%0448!  RAM1╞REE╠ENGTH    .BYTE 256-1-$04
  344. .%0449!
  345. .%0450!  CURRENT┼XP┬ANK = SYS╫ORK+$F
  346. .%0451!
  347. .%0452!  INIT─YNAMIC═EMORY = *
  348.  
  349. ╙ET THE MEMORY ALLOCATION FIRST FREE CHUNK POINTER TO ╬ULL AND SET THE NUMBER
  350. OF BYTES OF FREE MEMORY TO 0.
  351.  
  352. .%0453!     LDX #2
  353. .%0454!  -  LDA #$00
  354. .%0455!     STA FREE═EMORY,X
  355. .%0456!     LDA #$FF
  356. .%0457!     STA MALLOC╚EAD,X
  357. .%0458!     DEX
  358. .%0459!     BPL -
  359.  
  360. ─ETERMINE THE LENGTH OF FREE MEMORY ON ╥┴═0 AND FREE THE MEMORY.
  361.  
  362. .%0460!     SEC
  363. .%0461!     LDA $1212   ;TOP OF ┬┴╙╔├ PROGRAM ╠OW
  364. .%0462!     BEQ +
  365. .%0463!     CLC
  366. .%0464!  +  LDA $1213   ;TOP OF ┬┴╙╔├ PROGRAM ╚IGH
  367. .%0465!     SBC RAM0╞REE╙TART╨AGE
  368. .%0466!     TAY
  369. .%0467!     LDA RAM0╞REE╙TART╨AGE
  370. .%0468!     LDX #BK╥AM0
  371. .%0469!     JSR INIT╔NTERNAL┬ANK═ALLOC
  372.  
  373. ╞REE THE MEMORY OF ╥┴═1
  374.  
  375. .%0470!     LDA RAM1╞REE╙TART╨AGE
  376. .%0471!     LDY RAM1╞REE╠ENGTH
  377. .%0472!     LDX #BK╥AM1
  378. .%0473!     JSR INIT╔NTERNAL┬ANK═ALLOC
  379. .%0474!
  380.  
  381. ╞OR EACH EXISTING EXPANSION BANK, FREE IT FROM ADDRESSES $0000 TO $╞╞╞7.  ┘OU
  382. CANNOT FREE ALL 65536 BYTES SINCE THIS WOULD CAUSE THE LENGTH OF THE FREE
  383. CHUNK TO BE SET TO $0000 WHICH WOULD CAUSE PROBLEMS LATER ON.  $╞╞╞8 BYTES ARE
  384. SET TO FREE SINCE THEN LENGTH HAS TO BE A MULTIPLE OF EIGHT BYTES.
  385.  
  386. .%0475!     LDA #0
  387. .%0476!     STA CURRENT┼XP┬ANK
  388. .%0477!  -  LDA CURRENT┼XP┬ANK
  389. .%0478!     CMP N┼XP┬ANKS
  390. .%0479!     BCS +
  391. .%0480!     ORA #BK┼XP0
  392. .%0481!     STA ZP1+2
  393. .%0482!     LDA #$00
  394. .%0483!     STA ZP1
  395. .%0484!     STA ZP1+1
  396. .%0485!     LDA #$F8
  397. .%0486!     LDY #$FF
  398. .%0487!     JSR FREE
  399. .%0488!     INC CURRENT┼XP┬ANK
  400. .%0489!     BNE -
  401. .%0490!  +  RTS
  402. .%0491!
  403.  
  404. ╘HIS ROUTINE IS CALLED FOR FREEING BANKS ╥┴═0 AND ╥┴═1.  ╔T DOES NOTHING OTHER
  405. THAN SET PARAMETERS AND IS PUT IN FOR CONVENIENCE.
  406.  
  407. .%0492!  INIT╔NTERNAL┬ANK═ALLOC = *
  408. .%0493!     STA ZP1+1
  409. .%0494!     STX ZP1+2
  410. .%0495!     LDA #0
  411. .%0496!     STA ZP1
  412. .%0497!     JMP FREE
  413. .%0498!
  414. .%0499!  ;--------------------------------------------------------------------
  415. .%0500!  ;*** MALLOC( .┴┘=┬YTES ) : [ZP1]=╞AR╨OINTER
  416. .%0501!
  417.  
  418. ╧NE OF THE BIGGIES.  ╘HE "═EM╬EXT╨TR" AND "═EM╠ENGTH" VARIABLES ARE USED TO
  419. STORE THE INFORMATION AT THE START OF THE CURRENT FREE MEMORY CHUNK.  "╠ENGTH"
  420. IS USED TO HOLD THE LENGTH INPUT PARAMETER AND "╤" IS THE POINTER TO THE
  421. PREVIOUS FREE MEMORY CHUNK WHEREAS "ZP1" IS USED TO POINT TO THE CURRENT FREE
  422. CHUNK.  ╔ PREFIX THESE VARIABLES WITH "MALLOC" TO AVOID NAMING COLLISIONS WITH
  423. OTHER ROUTINES.  ╘HE CONCEPT OF LOCAL VARIABLES MIGHT BE A NICE THING FOR
  424. FUTURE ASSEMBLERS TO HAVE.
  425.  
  426. .%0502!  MALLOC═EM╬EXT╨TR = SYS╫ORK
  427. .%0503!  MALLOC═EM╠ENGTH  = SYS╫ORK+3
  428. .%0504!  MALLOC╠ENGTH     = SYS╫ORK+5
  429. .%0505!  MALLOC╤          = SYS╫ORK+7
  430. .%0506!
  431. .%0507!  INTERN┴LLOC = *
  432.  
  433. ┴LIGN THE NUMBER OF BYTES REQUESTED TO AN EVEN MULTIPLE OF EIGHT.
  434.  
  435. .%0508!     CLC
  436. .%0509!     ADC #7
  437. .%0510!     BCC +
  438. .%0511!     INY
  439. .%0512!  +  AND #$F8
  440. .%0513!     STA MALLOC╠ENGTH
  441. .%0514!     STY MALLOC╠ENGTH+1
  442.  
  443. ╙ET THE CURRENT FREE CHUNK POINTER TO THE FIRST FREE CHUNK AND SET ╤ TO ╬ULL.
  444.  
  445. .%0515!     LDX #2
  446. .%0516!  -  LDA MALLOC╚EAD,X
  447. .%0517!     STA ZP1,X
  448. .%0518!     LDA #$FF
  449. .%0519!     STA MALLOC╤,X
  450. .%0520!     DEX
  451. .%0521!     BPL -
  452. .%0522!
  453.  
  454. ╙EARCH FOR A FREE CHUNK THAT IS LONG ENOUGH TO SATISFY THE REQUEST.
  455.  
  456. .%0523!     MALLOC╠OOK = *
  457.  
  458. ╔F THE CURRENT FREE CHUNK POINTER IS ╬ULL, THEN WE ARE ╙.╧.╠. (╧UT OF ╠UCK)
  459. SINCE THAT MEANS WE HAVE EXHAUSTED THE LIST OF FREE CHUNKS AND HAVE TO REPORT
  460. THAT NO FREE MEMORY COULD BE FOUND.
  461.  
  462. .%0524!     LDA ZP1+2
  463. .%0525!     CMP #$FF
  464. .%0526!     BNE +
  465. .%0527!
  466. .%0528!     MALLOC┼RROR┼XIT = *
  467. .%0529!     LDA #$FF   ;RETURN A ╬ULL POINTER
  468. .%0530!     STA ZP1
  469. .%0531!     STA ZP1+1
  470. .%0532!     STA ZP1+2
  471. .%0533!     LDA #ERR╔NSUFFICIENT═EMORY
  472. .%0534!     STA ERRNO
  473. .%0535!     SEC
  474. .%0536!     RTS
  475. .%0537!
  476.  
  477. ╞ETCH THE HEADER INFORMATION OF THE CURRENT FREE CHUNK AND CHECK THE LENGTH.
  478. ╔F THE CURRENT FREE CHUNK IS NOT LARGE ENOUGH, THEN WE SET THE ╤ POINTER TO
  479. THE CURRENT POINTER, AND TAKE THE NEW VALUE FOR THE CURRENT POINTER FROM THE
  480. HEADER OF THE CURRENT FREE CHUNK (MALLOC═EM╬EXT╨TR) AND THEN CONTINUE
  481. SEARCHING.
  482.  
  483. .%0538!  +  LDX #MALLOC═EM╬EXT╨TR
  484. .%0539!     LDY #5
  485. .%0540!     JSR ZPLOAD
  486. .%0541!     LDA MALLOC═EM╠ENGTH
  487. .%0542!     CMP MALLOC╠ENGTH
  488. .%0543!     LDA MALLOC═EM╠ENGTH+1
  489. .%0544!     SBC MALLOC╠ENGTH+1
  490. .%0545!     BCS MALLOC╟OT┬LOCK
  491. .%0546!     LDX #2
  492. .%0547!  -  LDA ZP1,X
  493. .%0548!     STA MALLOC╤,X
  494. .%0549!     LDA MALLOC═EM╬EXT╨TR,X
  495. .%0550!     STA ZP1,X
  496. .%0551!     DEX
  497. .%0552!     BPL -
  498. .%0553!     JMP MALLOC╠OOK
  499. .%0554!
  500.  
  501. ╬OW, WE'VE FOUND A BLOCK THAT IS LARGE ENOUGH.
  502.  
  503. .%0555!     MALLOC╟OT┬LOCK = *
  504. .%0556!     SEC
  505.  
  506. ╙UBTRACT THE NUMBER OF BYTES REQUESTED FROM THE TOTAL NUMBER OF BYTES FREE.
  507.  
  508. .%0557!     LDA FREE═EMORY
  509. .%0558!     SBC MALLOC╠ENGTH
  510. .%0559!     STA FREE═EMORY
  511. .%0560!     LDA FREE═EMORY+1
  512. .%0561!     SBC MALLOC╠ENGTH+1
  513. .%0562!     STA FREE═EMORY+1
  514. .%0563!     BCS +
  515. .%0564!     DEC FREE═EMORY+2
  516.  
  517. ╔F THE SIZE OF THE CURRENT FREE CHUNK IS EXACTLY THE SAME AS THE NUMBER OF
  518. BYTES REQUESTED, THEN BRANCH AHEAD.
  519.  
  520. .%0565!  +  LDA MALLOC═EM╠ENGTH
  521. .%0566!     CMP MALLOC╠ENGTH
  522. .%0567!     BNE +
  523. .%0568!     LDA MALLOC═EM╠ENGTH+1
  524. .%0569!     SBC MALLOC╠ENGTH+1
  525. .%0570!     BEQ MALLOC╘AKE╫HOLE┬LOCK
  526.  
  527. ╙UBTRACT THE NUMBER OF BYTES REQUESTED FROM THE LENGTH OF THE CURRENT FREE
  528. CHUNK AND THEN WRITE THE UPDATED HEADER BACK TO THE CURRENT FREE CHUNK.
  529.  
  530. .%0571!  +  SEC
  531. .%0572!     LDA MALLOC═EM╠ENGTH
  532. .%0573!     SBC MALLOC╠ENGTH
  533. .%0574!     STA MALLOC═EM╠ENGTH
  534. .%0575!     LDA MALLOC═EM╠ENGTH+1
  535. .%0576!     SBC MALLOC╠ENGTH+1
  536. .%0577!     STA MALLOC═EM╠ENGTH+1
  537. .%0578!     LDX #MALLOC═EM╬EXT╨TR
  538. .%0579!     LDY #5
  539. .%0580!     JSR ZPSTORE
  540.  
  541. ┴DD THE LENGTH OF THE FREE CHUNK TO THE POINTER TO THE START OF THE FREE CHUNK
  542. TO DETERMINE THE ADDRESS OF THE MEMORY THAT HAS JUST BEEN ALLOCATED.  ╘HEN
  543. EXIT, RETURNING THIS ADDRESS.
  544.  
  545. .%0581!     CLC
  546. .%0582!     LDA ZP1
  547. .%0583!     ADC MALLOC═EM╠ENGTH
  548. .%0584!     STA ZP1
  549. .%0585!     LDA ZP1+1
  550. .%0586!     ADC MALLOC═EM╠ENGTH+1
  551. .%0587!     STA ZP1+1
  552. .%0588!     CLC
  553. .%0589!     RTS
  554. .%0590!
  555.  
  556. ╚ERE, THE SIZE OF THE FREE CHUNK IS EXACTLY THE SAME SIZE AS THE REQUEST, SO
  557. THE ENTIRE BLOCK HAS TO BE ALLOCATED AND THUS REMOVED FROM THE FREE CHUNK
  558. LIST.  ╘HIS IS WHY THE ╤ POINTER HAS BEEN MAINTAINED.
  559.  
  560. .%0591!     MALLOC╘AKE╫HOLE┬LOCK = *
  561.  
  562. ╔F THERE IS NO PREVIOUS BLOCK (╤ == ╬ULL) THEN SET THE FREE CHUNK LIST HEAD
  563. POINTER TO THE NEXT FREE CHUNK AFTER THE CURRENT ONE.  ╘HEN EXIT WITH THE
  564. CURRENT CHUNK AS THE RETURN POINTER.
  565.  
  566. .%0592!     LDA MALLOC╤+2
  567. .%0593!     CMP #BK╬ULL
  568. .%0594!     BNE +
  569. .%0595!     LDX #2
  570. .%0596!  -  LDA MALLOC═EM╬EXT╨TR,X
  571. .%0597!     STA MALLOC╚EAD,X
  572. .%0598!     DEX
  573. .%0599!     BPL -
  574. .%0600!     CLC
  575. .%0601!     RTS
  576.  
  577. ╔F THERE IS AN ACTUAL PREVIOUS CHUNK, THEN WE HAVE TO SET IT TO POINT TO THE
  578. NEXT CHUNK FROM THE CURRENT CHUNK.  ╘HIS WILL UNLINK THE CURRENT FREE CHUNK
  579. FROM THE FREE CHUNK LIST, THEREBY ALLOCATING IT.
  580.  
  581. ╞IRST, WE SWAP THE ╤ AND CURRENT POINTERS, SINCE WE CAN ONLY ACCESS MEMORY
  582. THROUGH THE "ZP1" POINTER.
  583.  
  584. .%0602!  +  LDX #2
  585. .%0603!  -  LDA ZP1,X
  586. .%0604!     LDY MALLOC╤,X
  587. .%0605!     STA MALLOC╤,X
  588. .%0606!     STY ZP1,X
  589. .%0607!     DEX
  590. .%0608!     BPL -
  591.  
  592. ╘HEN WE SET THE THE ╬EXT╨OINTER OF THE PREVIOUS FREE CHUNK TO POINT TO THE
  593. NEXT FREE CHUNK AFTER THE CURRENT CHUNK.
  594.  
  595. .%0609!     LDX #MALLOC═EM╬EXT╨TR
  596. .%0610!     LDY #3
  597. .%0611!     JSR ZPSTORE
  598.  
  599. ┴ND THEN WE RESTORE THE CURRENT CHUNK POINTER AND RETURN IT TO THE USER.
  600.  
  601. .%0612!     LDX #2
  602. .%0613!  -  LDA MALLOC╤,X
  603. .%0614!     STA ZP1,X
  604. .%0615!     DEX
  605. .%0616!     BPL -
  606. .%0617!     CLC
  607. .%0618!     RTS
  608. .%0619!
  609. .%0620!  ;*** FREE( [ZP1]=╞AR╨OINTER, .┴┘=╠ENGTH )  █ALTERS [ZP1]▌
  610. .%0621!
  611.  
  612. ┴ND HERE IS THE REAL BIGGIE, SINCE ╞REE IS MORE COMPLICATED THAN ═ALLOC.  ╘HE
  613. VARIABLES ARE THE SAME AS FOR FREE, EXCEPT THAT "╬EW╨TR" IS REQUIRED TO
  614. REMEMBER THE INPUT PARAMETER TO NEW CHUNK TO BE FREED.
  615.  
  616. .%0622!  FREE═EM╬EXT╨TR = SYS╫ORK
  617. .%0623!  FREE═EM╠ENGTH  = SYS╫ORK+3
  618. .%0624!  FREE╠ENGTH     = SYS╫ORK+5
  619. .%0625!  FREE╬EW╨TR     = SYS╫ORK+7
  620. .%0626!  FREE╤          = SYS╫ORK+10
  621. .%0627!
  622. .%0628!  INTERN╞REE = *
  623.  
  624. ┴GAIN, ALIGN THE LENGTH OF THE CHUNK.  ╘HE POINTER TO THE START OF THE NEW
  625. CHUNK IS ASSUMED TO BE ALIGNED (SINCE MALLOC ONLY RETURNS ALIGNED CHUNKS).  ╔F
  626. THE CHUNK POINTER IS NOT ALIGNED, ALL HELL CAN BREAK LOOSE.
  627.  
  628. .%0629!     CLC
  629. .%0630!     ADC #7
  630. .%0631!     BCC +
  631. .%0632!     INY
  632. .%0633!  +  AND #$F8
  633. .%0634!     STA FREE╠ENGTH
  634. .%0635!     STY FREE╠ENGTH+1
  635.  
  636. ╙AVE THE NEW CHUNK INPUT PARAMETER AND SET "ZP1" FOR SEARCHING THE FREE CHUNK
  637. LIST.  ┴LSO SET ╤ TO ╬ULL SINCE ╤ WILL BE USED TO REMEMBER THE PREVIOUS BLOCK
  638. TO "ZP1".
  639.  
  640. .%0636!     LDX #2
  641. .%0637!  -  LDA ZP1,X
  642. .%0638!     STA FREE╬EW╨TR,X
  643. .%0639!     LDA MALLOC╚EAD,X
  644. .%0640!     STA ZP1,X
  645. .%0641!     LDA #$FF
  646. .%0642!     STA FREE╤,X
  647. .%0643!     DEX
  648. .%0644!     BPL -
  649. .%0645!
  650.  
  651. ╙EARCH FOR THE TWO FREE CHUNKS WHOSE ADDRESSES STRADDLE THE NEW FREE CHUNK.
  652.  
  653. .%0646!     FREE╙EARCH╠OOP = *
  654.  
  655. ╔F THE CURRENT FREE CHUNK POINTER IS ╬ULL OR IF THE CURRENT FREE CHUNK'S BANK
  656. NUMBER IS LESS THAN THE NEW CHUNK'S BANK NUMBER, THEN WE CAN STOP SEARCHING;
  657. WE HAVE FOUND A FREE CHUNK THAT IS "HIGHER" THAN THE NEW CHUNK, SO ╤ AND ZP1
  658. MUST STRADDLE THE ADDRESS OF THE NEW CHUNK.  ╬OTE THAT BY USING A "BCC" ON
  659. LINE 652, EXTERNAL MEMORY FREE CHUNKS WILL BE ALLOCATED FIRST.  ╔F ╔ HAD USED
  660. A "BCS" THERE, THE INTERNAL MEMORY STARTING FROM ╥┴═0 WOULD BE ALLOCATED
  661. FIRST.
  662.  
  663. .%0647!     LDA ZP1+2
  664. .%0648!     CMP #$FF
  665. .%0649!     BEQ FREE├OALESCE╤AND╬EW
  666. .%0650!     LDA ZP1+2
  667. .%0651!     CMP FREE╬EW╨TR+2
  668. .%0652!     BCC FREE├OALESCE╤AND╬EW  ;** DETERMINES BANK ORDER
  669.  
  670. ╚ERE WE KNOW THAT THE BANK NUMBER IS NOT "HIGHER", SO IF THE BANK NUMBERS ARE
  671. NOT EQUAL, THEN WE CONTINUE SEARCHING.  ╔F THE BANK NUMBERS ARE EQUAL, WE MUST
  672. CHECK THE ADDRESSES WITHIN THE BANK TO SEE IF ZP1 IS HIGHER THAN THE NEW
  673. CHUNK.  ╔F SO, WE STOP SEARCHING.
  674.  
  675. .%0653!     BNE +
  676. .%0654!     LDA ZP1
  677. .%0655!     CMP FREE╬EW╨TR
  678. .%0656!     LDA ZP1+1
  679. .%0657!     SBC FREE╬EW╨TR+1
  680. .%0658!     BCS FREE├OALESCE╤AND╬EW
  681.  
  682. ╚ERE WE CONTINUE SEARCHING.  ╫E STICK THE CURRENT FREE CHUNK POINTER INTO ╤
  683. AND GET THE NEXT FREE CHUNK POINTER FROM THE CURRENT CHUNK IN MEMORY.  ╘HEN WE
  684. GO BACK TO THE TOP OF THE SEARCH.
  685.  
  686. .%0659!  +  LDX #FREE═EM╬EXT╨TR
  687. .%0660!     LDY #3
  688. .%0661!     JSR ZPLOAD
  689. .%0662!     LDX #2
  690. .%0663!  -  LDA ZP1,X
  691. .%0664!     STA FREE╤,X
  692. .%0665!     LDA FREE═EM╬EXT╨TR,X
  693. .%0666!     STA ZP1,X
  694. .%0667!     DEX
  695. .%0668!     BPL -
  696. .%0669!     BMI FREE╙EARCH╠OOP
  697. .%0670!
  698.  
  699. ╚ERE WE KNOW THAT ╤ AND ZP1 STRADDLE THE NEW CHUNK, AND WE TRY TO COALESCE THE
  700. NEW CHUNK TO THE ╤ CHUNK.
  701.  
  702. .%0671!     FREE├OALESCE╤AND╬EW = *
  703. .%0672!     LDX #2
  704. .%0673!  -  LDA FREE╤,X
  705. .%0674!     STA ZP1,X
  706. .%0675!     DEX
  707. .%0676!     BPL -
  708.  
  709. ╔F THE ╤ POINTER IS ╬ULL, THEN THERE IS NO ╤ CHUNK TO COALESCE WITH, SO THE
  710. FREE CHUNK HEAD POINTER IS SET TO POINT TO THE NEW CHUNK AND THE NEW CHUNK
  711. HEADER IS SET TO THE SIZE OF THE NEW CHUNK.  ╘HEN NEXT POINTER FOR THE NEW
  712. CHUNK IS SET TO WHAT WAS PREVIOUSLY THE HEAD POINTER.
  713.  
  714. .%0677!     LDA ZP1+2
  715. .%0678!     CMP #$FF
  716. .%0679!     BNE +
  717. .%0680!     LDX #2
  718. .%0681!  -  LDA MALLOC╚EAD,X
  719. .%0682!     STA FREE═EM╬EXT╨TR,X
  720. .%0683!     LDA FREE╬EW╨TR,X
  721. .%0684!     STA MALLOC╚EAD,X
  722. .%0685!     DEX
  723. .%0686!     BPL -
  724. .%0687!     LDA FREE╠ENGTH
  725. .%0688!     LDY FREE╠ENGTH+1
  726. .%0689!     STA FREE═EM╠ENGTH
  727. .%0690!     STY FREE═EM╠ENGTH+1
  728. .%0691!     JMP FREE├OALESCE╬EW┴ND╨
  729. .%0692!
  730.  
  731. ╚ERE THERE ACTUALLY IS A PREVIOUS (╤) CHUNK, SO ITS HEADER IS FETCHED.  ╔F IT
  732. IS NOT ON THE SAME BANK AS THE NEW CHUNK, THEN THE NEW CHUNK CANNOT BE
  733. COALESCED WITH IT.  ┴LSO, IF THE ADDRESS OF THE NEW CHUNK DOES NOT EXACTLY
  734. FOLLOW THE ╤ CHUNK, THEN THEY CANNOT BE COALESCED.
  735.  
  736. .%0693!  +  LDX #FREE═EM╬EXT╨TR
  737. .%0694!     LDY #5
  738. .%0695!     JSR ZPLOAD
  739. .%0696!     LDA ZP1+2
  740. .%0697!     CMP FREE╬EW╨TR+2
  741. .%0698!     BNE +
  742. .%0699!     CLC
  743. .%0700!     LDA ZP1
  744. .%0701!     ADC FREE═EM╠ENGTH
  745. .%0702!     TAX
  746. .%0703!     LDA ZP1+1
  747. .%0704!     ADC FREE═EM╠ENGTH+1
  748. .%0705!     CMP FREE╬EW╨TR+1
  749. .%0706!     BNE +
  750. .%0707!     CPX FREE╬EW╨TR
  751. .%0708!     BNE +
  752.  
  753. ╚ERE, WE KNOW THAT THE PREVIOUS CHUNK AND THE NEW CHUNK CAN BE COALESCED.  ╫E
  754. ADD THE LENGTH OF THE NEW CHUNK TO THE LENGTH OF THE PREVIOUS CHUNK AND CHANGE
  755. THE NEW CHUNK POINTER TO POINT TO THE PREVIOUS CHUNK.
  756.  
  757. .%0709!     CLC
  758. .%0710!     LDA FREE═EM╠ENGTH
  759. .%0711!     ADC FREE╠ENGTH
  760. .%0712!     STA FREE═EM╠ENGTH
  761. .%0713!     LDA FREE═EM╠ENGTH+1
  762. .%0714!     ADC FREE╠ENGTH+1
  763. .%0715!     STA FREE═EM╠ENGTH+1
  764. .%0716!     LDX #2
  765. .%0717!  -  LDA FREE╤,X
  766. .%0718!     STA FREE╬EW╨TR,X
  767. .%0719!     DEX
  768. .%0720!     BPL -
  769. .%0721!     BMI FREE├OALESCE╬EW┴ND╨
  770. .%0722!
  771.  
  772. ╚ERE, WE KNOW THAT THE PREVIOUS AND NEW CHUNKS CANNOT BE COALESCED.  ╫E CHANGE
  773. THE ACTUAL HEADER OF THE PERVIOUS CHUNK TO POINT TO THE NEW CHUNK AND CHANGE
  774. THE NEW CHUNK HEADER LENGTH TO THE FREE REQUEST LENGTH.  ╘HE POINTER TO THE
  775. NEXT CHUNK IS ALREADY IN THE NEW CHUNK HEADER FROM BEFORE.  ╬OTE THAT NOW WE
  776. ARE USING "═EM╬EXT╨TR" AND "═EM╠ENGTH" TO CONSTRUCT THE NEW FREE CHUNK
  777. HEADER.  ╠INE 729 CAUSED ═R. ┬RUCE SOME PROBLEMS BECAUSE HE FORGOT TO STICK
  778. THE "+1" THERE AFTER EXTRACTING THE CODE FROM ┌ED.
  779.  
  780. .%0723!  +  LDX #FREE╬EW╨TR
  781. .%0724!     LDY #3
  782. .%0725!     JSR ZPSTORE
  783. .%0726!     LDA FREE╠ENGTH
  784. .%0727!     LDY FREE╠ENGTH+1
  785. .%0728!     STA FREE═EM╠ENGTH
  786. .%0729!     STY FREE═EM╠ENGTH+1
  787. .%0730!
  788.  
  789. ┴T THIS POINT, WE ARE FINISHED TRYING TO COALESCE THE NEW CHUNK WITH THE
  790. PREVIOUS CHUNK, SO WE WILL ATTEMPT TO COALESCE THE NEW CHUNK WITH THE NEXT
  791. HIGHER ADDRESS FREE CHUNK.  ╘HE "═EM╬EXT╨TR" AND "═EM╠ENGTH" VARIABLES HOLD
  792. THE HEADER INFORMATION FOR THE NEW CHUNK (THE "═EM╬EXT╨TR" ALSO POINTS TO THE
  793. NEXT FREE CHUNK), AND "╬EW╨TR" POINTS TO THE NEW CHUNK.  ╫E CHECK TO SEE IF
  794. THE NEW CHUNK IMMEDIATELY PRECEEDS THE NEXT CHUNK IN THE SAME WAY AS BEFORE.
  795. ╬OTE THAT THE CASE OF A ╬ULL NEXT CHUNK POINTER IS HANDLED HERE IMPLICITLY,
  796. SINCE THE BANK NUMBERS WON'T MATCH.
  797.  
  798. .%0731!     FREE├OALESCE╬EW┴ND╨ = *
  799. .%0732!     LDA FREE╬EW╨TR+2
  800. .%0733!     CMP FREE═EM╬EXT╨TR+2
  801. .%0734!     BNE +
  802. .%0735!     CLC
  803. .%0736!     LDA FREE╬EW╨TR
  804. .%0737!     ADC FREE═EM╠ENGTH
  805. .%0738!     TAX
  806. .%0739!     LDA FREE╬EW╨TR+1
  807. .%0740!     ADC FREE═EM╠ENGTH+1
  808. .%0741!     CMP FREE═EM╬EXT╨TR+1
  809. .%0742!     BNE +
  810. .%0743!     CPX FREE═EM╬EXT╨TR
  811. .%0744!     BNE +
  812. .%0745!
  813.  
  814. ╚ERE, WE KNOW THAT THE NEW CHUNK CAN BE COALESCED WITH THE NEXT CHUNK.  ╫E
  815. HAVE TO FETCH THE HEADER OF THE NEXT CHUNK TO KNOW THE LENGTH AND THE POINTER
  816. TO THE FREE CHUNK AFTER THE NEXT CHUNK.  ╫E THEN ADD THE LENGTH OF THE NEXT
  817. CHUNK TO THE LENGTH OF THE NEW CHUNK AND KEEP THE POINTER TO THE CHUNK AFTER
  818. THE NEXT CHUNK FOR THE NEW CHUNK HEADER.  ┼FFECTIVELY, THE NEXT FREE CHUNK IS
  819. UNLINKED (SINCE NOTHING IS LEFT TO POINT TO IT) AND THE NEW CHUNK GROWS TO
  820. SWALLOW IT UP.
  821.  
  822. .%0746!     LDX #2
  823. .%0747!  -  LDA FREE═EM╬EXT╨TR,X
  824. .%0748!     STA ZP1,X
  825. .%0749!     DEX
  826. .%0750!     BPL -
  827. .%0751!     LDA FREE═EM╠ENGTH+1
  828. .%0752!     PHA
  829. .%0753!     LDA FREE═EM╠ENGTH
  830. .%0754!     PHA
  831. .%0755!     LDX #FREE═EM╬EXT╨TR
  832. .%0756!     LDY #5
  833. .%0757!     JSR ZPLOAD
  834. .%0758!     CLC
  835. .%0759!     PLA
  836. .%0760!     ADC FREE═EM╠ENGTH
  837. .%0761!     STA FREE═EM╠ENGTH
  838. .%0762!     PLA
  839. .%0763!     ADC FREE═EM╠ENGTH+1
  840. .%0764!     STA FREE═EM╠ENGTH+1
  841. .%0765!
  842.  
  843. ╚ERE, WE WRAP THINGS UP.  ╫E HAVE THE HEADER FOR THE NEW FREE CHUNK ALL
  844. PREPARED AND WE HAVE TRIED TO COALESCE THE TWO NEIGHBORING CHUNKS TO THE NEW
  845. CHUNK.  ┴LL WE DO NOW IS WRITE THE NEW CHUNK HEADER OUT TO MAIN MEMORY AND
  846. INCREASE THE NUMBER OF BYTES FREE VARIABLE BY THE LENGTH OF THE (ORIGINAL)
  847. FREE REQUEST.
  848.  
  849. .%0766!  +  LDX #2
  850. .%0767!  -  LDA FREE╬EW╨TR,X
  851. .%0768!     STA ZP1,X
  852. .%0769!     DEX
  853. .%0770!     BPL -
  854. .%0771!     LDX #FREE═EM╬EXT╨TR
  855. .%0772!     LDY #5
  856. .%0773!     JSR ZPSTORE
  857. .%0774!     CLC
  858. .%0775!     LDA FREE═EMORY
  859. .%0776!     ADC FREE╠ENGTH
  860. .%0777!     STA FREE═EMORY
  861. .%0778!     LDA FREE═EMORY+1
  862. .%0779!     ADC FREE╠ENGTH+1
  863. .%0780!     STA FREE═EMORY+1
  864. .%0781!     BCC +
  865. .%0782!     INC FREE═EMORY+2
  866.  
  867. ╫E ALWAYS RETURN WITH CARRY CLEARED, SINCE WE DON'T CHECK FOR ANY ERRORS.
  868.  
  869. .%0783!  +  CLC
  870. .%0784!     RTS
  871. .%0785!
  872. .%0786!  ;--------------------------------------------------------------------
  873. .%0787!  ;*** SORT - THE APPLICATION: READS FROM FILE #1, WRITES TO FILE #2
  874. .%0788!
  875.  
  876. ╘HIS IS WHERE THE ACTUAL APPLICATION CODE STARTS.  ╔F YOU WANT TO WRITE YOUR
  877. OWN PROGRAM THAT USES THE DYNAMIC MEMORY ALLOCATION PACKAGE, THEN YOU CAN
  878. FOLLOW THE STRUCTURE OF THIS APPLICATION.
  879.  
  880. ╫E START OFF BY DECLARING THE STORAGE AREAS FOR THE CURRENT LINE BEING
  881. PROCESSED AND FOR THE LINE BEING COMPARED TO THE CURRENT LINE.  ╘HE ADDRESSES
  882. REFLECT THE STRUCTURE OF THE RECORD FOR THE INPUT LINE THAT WAS DISCUSSED
  883. EARLIER.  ╘HE SORTING FIELD STARTING COLUMN NUMBER PARAMETER IS CAN BE PUT AT
  884. $8╞╞ SINCE THE INPUT LINE CAN ONLY BE 242 CHARACTERS LONG.
  885.  
  886. .%0789!  SORTBUF    = $B00
  887. .%0790!  SORTBUFLEN = $B03
  888. .%0791!  SORTLINE   = $B04
  889. .%0792!  CMPBUF     = $800
  890. .%0793!  CMPBUFLEN  = $803
  891. .%0794!  CMPLINE    = $804
  892. .%0795!  SORT├OLUMN = $8FF
  893. .%0796!
  894.  
  895. ╘HESE ARE THE ZERO PAGE LOCATIONS THAT SORT USES.
  896.  
  897. .%0797!  EOFSTAT  = $02  ;DEFERRED ╙╘ VARIABLE ($90)
  898. .%0798!  SORTHEAD = $03  ;POINTER TO FIRST LINE IN LINE LIST
  899. .%0799!  SORT╨    = $06  ;CURRENT LINE FOR LIST SEARCHING
  900. .%0800!  SORT╤    = $09  ;PREVIOUS LINE FOR LIST SEARCHING
  901. .%0801!  HEADER   = $0C  ;4 BYTES - HOLDS THE CURRENT LINE RECORD'S HEADER
  902. .%0802!
  903.  
  904. ┴ND THESE ARE THE KERNEL ROUTINES THAT ARE CALLED.
  905.  
  906. .%0803!  KERNEL├HKIN  = $FFC6
  907. .%0804!  KERNEL├HKOUT = $FFC9
  908. .%0805!  KERNEL├LRCHN = $FFCC
  909. .%0806!  KERNEL├HRIN  = $FFCF
  910. .%0807!  KERNEL├HROUT = $FFD2
  911.  
  912. "ECHO╙TATUS" CAN BE CHANGED TO POINT TO AN ╥╘╙ IF YOU DO NOT WANT SORT TO
  913. PRINT STATUS INFORMATION OUT WHILE IT IS WORKING.
  914.  
  915. .%0808!  ECHO╙TATUS   = KERNEL├HROUT
  916. .%0809!
  917. .%0810!  ;*** GETLINE( SORTLINE ) : .├╙=EOF
  918. .%0811!
  919.  
  920. ╘HIS ROUTINE READS A NEW LINE IN FROM THE CURRENT INPUT CHANNEL AND PUTS IT
  921. INTO THE PROCESSING BUFFER.  ╔T RETURNS WITH CARRY SET IF THERE ARE NO MORE
  922. LINES TO READ OR IF A READ ERROR OCCURS.
  923.  
  924. .%0812!  GETLINE = *
  925. .%0813!     LDY #0
  926.  
  927. ╘HE "EOFSTAT" IS CHECKED FIRST TO SEE IF THE PREVIOUS CHARACTER READ BEFORE
  928. THE NEW CALL WAS THE LAST OF THE FILE.  ╘HIS OVERCOMES THE KERNEL'S AWKWARD
  929. WAY OF SETTING ┼╧╔ FOR THE LAST CHARACTER RATHER THAN WHEN FOR WHEN YOU GO
  930. BEYOND THE LAST CHARACTER.
  931.  
  932. .%0814!  -  BIT EOFSTAT
  933. .%0815!     BVS GETLINE┼OF
  934. .%0816!     JSR KERNEL├HRIN
  935. .%0817!     BCS GETLINE┼OF
  936. .%0818!     STA SORTLINE,Y
  937. .%0819!     INY
  938. .%0820!     LDX $90
  939. .%0821!     STX EOFSTAT
  940.  
  941. ╔T EXITS WHEN THE MAXIMUM LINE LENGTH IS EXCEEDED OR WHEN A CARRIAGE RETURN IS
  942. ENCOUNTERED.
  943.  
  944. .%0822!     CPY #242
  945. .%0823!     BCS GETLINE┼XIT
  946. .%0824!     CMP #13
  947. .%0825!     BNE -
  948. .%0826!     DEY
  949. .%0827!
  950.  
  951. ┴ TRAILING '\0' IS APPENDED TO THE STRING FOR EASIER PROCESSING LATER, AND THE
  952. LENGTH OF THE INPUT LINE RECORD IS RECORDED.  ╘HE LENGTH OF THE ENTIRE RECORD
  953. RATHER THAN THE LENGTH OF JUST THE TEXT IS MORE CONVENIENT TO KNOW WHEN
  954. WORKING WITH THE MEMORY PACKAGE.
  955.  
  956. .%0828!     GETLINE┼XIT = *
  957. .%0829!     LDA #0
  958. .%0830!     STA SORTLINE,Y
  959. .%0831!     CLC
  960. .%0832!     TYA
  961. .%0833!     ADC #5
  962. .%0834!     STA SORTBUFLEN
  963. .%0835!     CLC
  964. .%0836!     RTS
  965. .%0837!
  966.  
  967. ╧N END OF FILE, WE EXIT WITH CARRY SET.  ╔F, HOWEVER, WE HAVE READ CHARACTERS
  968. BEFORE THE ┼╧╞ WAS ENCOUNTERED, THEY ARE RETURNED AS BELONGING TO THE LAST
  969. LINE OF THE FILE.  ╘RUE ┼╧╞ WILL BE RETURNED ON THE NEXT CALL.
  970.  
  971. .%0838!     GETLINE┼OF = *
  972. .%0839!     LDA #$40
  973. .%0840!     STA EOFSTAT
  974. .%0841!     CPY #0
  975. .%0842!     BNE GETLINE┼XIT
  976. .%0843!     SEC
  977. .%0844!     RTS
  978. .%0845!
  979. .%0846!  ;*** PUTLINE( APPLINE )
  980. .%0847!
  981.  
  982. ╘HIS ROUTINE SIMPLY WRITES OUT THE CURRENT LINE ('\0' TERMINATED) AND WRITES
  983. AN ADDITIONAL CARRIAGE RETURN, SINCE THE GETLINE ROUTINE STRIPS OFF THE ├╥.
  984.  
  985. .%0848!  PUTLINE = *
  986. .%0849!     LDY #0
  987. .%0850!  -  LDA SORTLINE,Y
  988. .%0851!     BEQ +
  989. .%0852!     JSR KERNEL├HROUT
  990. .%0853!     INY
  991. .%0854!     BNE -
  992. .%0855!  +  LDA #13
  993. .%0856!     JMP KERNEL├HROUT
  994. .%0857!
  995. .%0858!  ;*** FETCHLINE( SORT╨=╠INE╨TR, .┴┘=╥AM0BUF )
  996. .%0859!
  997.  
  998. ╘HIS ROUTINE FETCHES THE LINE AT THE POINTER SORT╨ INTO ╥┴═0 AT THE GIVEN
  999. ADDRESS.  ╔T HAS TO ZPLOAD THE LINE HEADER FIRST TO DETERMINE THE RECORD SIZE
  1000. TO FETCH.
  1001.  
  1002.